home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_200
/
266_01
/
drawlib.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-02
|
10KB
|
337 lines
/* Front End Plot Utility Routines File: DRAWLIB.C
Robert L. Patton, Jr.
1713 Parkcrest Terrace
Arlington, TX 76012
04-30-89
*/
#include <math.h>
#include "PLOX.H"
#include "DRAWLIB.H"
#include "MATHLIB.H"
#include "PXLIB.H"
#define AX Scale->
void Annote (X, Y, Offset, Dir, Mode, Side, Word, Font)
/* ====== */
/* Draws upright text at a given offset from
a point on a line in a given direction. */
int X,Y; /* coordinates of point, pixels */
int Offset; /* distance from line, pixels */
char Dir; /* line direction, 'H' or 'V' */
int Mode; /* 0 = text parallel to line centered on point
1 = text perpendicular, ended at point */
int Side; /* 1 = clockwise, -1 = ccw */
char *Word; /* the text string */
int Font; /* predefined character set number */
{
int S, C, Tlen, Xt, Yt, Adjust, Pica;
Pica = TxHigh (Font);
Tlen = TxWide (strlen (Word), Font);
S = Isin(Dir);
C = Icos(Dir);
Xt = X + Offset * S * Side;
Yt = Y - Offset * C * Side;
if (Mode) {
Adjust = Tlen * (1 - Side);
Xt += (C*Pica - S*Adjust) / 2;
Yt -= (S*Pica + C*Adjust) / 2;
}
else {
Xt -= (C*Tlen - S*Pica) / 2;
Yt -= (S*Tlen + C*Pica) / 2;
}
PX_Text (Xt, Yt, Font, 'H', Word);
}
void AxNum (Xa, Ya, Dir, Side, Span, Scale, Boxes)
/* ===== */
/* Draws a standard numeric axis */
int Xa,Ya; /* start coordinates, pixels */
char Dir; /* direction, 'H' or 'V' */
int Side; /* side for numbers, 1=CW, -1=CCW */
int Span; /* length of axis, pixels */
SCALING *Scale;/* pointer to scaling values */
int Boxes; /* number of divisions */
{
double Value;
char Digits[30];
int Bump, C, Font, Mode, S, X, Y;
static unsigned Flag=2, Left=0, Right=1;
#ifdef DEBUG
printf("AxNum:Xa=%d,Ya=%d,Dir=%c,Side=%d,Span=%d,Boxes=%d\n",
Xa,Ya,Dir,Side,Span,Boxes);
ShowScale(Dir,Boxes,Scale);
#endif
Font = 1; /* optional font later */
S = Isin(Dir);
C = Icos(Dir);
Mode = (Dir == 'V');
PX_Move (Xa, Ya);
PX_Draw (Xa+Span*C, Ya+Span*S);
X = Xa;
Y = Ya;
for (Value=AX Start; Value<=(AX Start+Boxes*AX DeltaB); Value+=AX DeltaB)
{
Bump = (int) ((Value-AX Start)*AX DeltaP+.5);
X = Xa+C*Bump;
Y = Ya+S*Bump;
TicMark (X, Y, 3, Dir, Side);
Ftoa (Value, Digits);
Annote (X, Y, 8-3*Mode, Dir, Mode, Side, Digits, Font);
}
}
/*@@*/
void Bar (X1, Y1, X2, Y2, Dir, Width, Hatch)
/* === Draws a rectangular bar */
int X1,Y1, /* center of one end */
X2,Y2, /* center of other end */
Width, /* width in pixels */
Hatch; /* hatching pattern */
char Dir; /* direction, H or V */
{
int Xa, Ya, Xc, Yc, Xhalf, Yhalf;
Xhalf = (Width * Isin(Dir)) >> 1;
Yhalf = (Width * Icos(Dir)) >> 1;
Xa = X1 + Xhalf;
Ya = Y1 - Yhalf; /* diagonally */
Xc = X2 - Xhalf; /* opposite */
Yc = Y2 + Yhalf; /* corners */
if (Hatch!=0) PX_Hatch (Xa,Ya,Xc,Yc);
PX_Move (Xa,Ya);
PX_Draw (Xa,Yc);
PX_Draw (Xc,Yc);
PX_Draw (Xc,Ya);
PX_Draw (Xa,Ya);
}
void Box (X1,Y1,X2,Y2)
/* === Draw a rectangle */
int X1,Y1,X2,Y2;
{
PX_Move(X1,Y1);
PX_Draw(X2,Y1);
PX_Draw(X2,Y2);
PX_Draw(X1,Y2);
PX_Draw(X1,Y1);
}
void BoxTry (Span,MinBox,MaxBox)
/* ====== Choose the minimum and maximum */
int Span, *MinBox, *MaxBox; /* number of scale divisions to try */
{ /* for any given span in pixels. */
if (Span<(1.5*INCH)) {
*MinBox = 2;
*MaxBox = 2;
}
else {
*MinBox = Span/INCH;
if (*MinBox<3) *MinBox = 3;
*MaxBox = 2*( *MinBox);
}
}
void CopyScale (From, To)
/* ========= Makes a copy of a SCALING value */
SCALING *From, *To;
{
To->Start = From->Start;
To->DeltaB = From->DeltaB;
To->DeltaP = From->DeltaP;
}
void Fit (Min, Max, Boxes, Start, Delta)
/* === */
int Boxes; /* Finds offset and units/division for */
double Min,Max; /* a given range and number of divisions */
double *Start,*Delta; /* ensuring 1,2,4, or 5 X 10**N per division */
{
double Divs;
int Trial=0;
Divs = (double) Boxes;
*Delta = 0.5 * Exp10 ((int) floor ((log10 (Max-Min)/Divs)) );
do
{
Trial += 1;
if (Trial%4 == 3)
*Delta = 1.25 * *Delta;
else *Delta = 2.00 * *Delta;
*Start = *Delta * floor (Min / *Delta);
}
while (*Start + Divs * *Delta < Max);
}
/*@@*/
int IsHue (char *Word) {
/* ===== Returns the color number if Word is a
microPLOX color. Otherwise zero.
*/
#define HUES 15
#define HUEBUF 8
char *HueList[HUES] = {"blue " ,"pea" ,"aqua" ,"coral" ,"plum",
"umber" ,"chalk" ,"gray" ,"azure" ,"lime",
"cyan" ,"peach" ,"lilac" ,"lemon" ,"white"};
int HueNum;
HueNum = iKeyFind (HueList,HUES,Word);
return (HueNum<0 ? 0 : HueNum);
}
void Liner (Xptr, Xfit, Yptr, Yfit, LineType, PointType)
/* ===== Draws straight lines between consecutive points in a set
of X,Y points in arbitrary data units */
float *Xptr,*Yptr; /* the data points */
SCALING *Xfit,*Yfit; /* scaling parameters */
int LineType, /* line pattern, 1=solid */
PointType; /* point shape, 0=none */
{
int I, Imax;
PX_Trail (LineType);
Imax = (int) *Xptr++;
Yptr++;
PX_Move (Scaled(Xptr++,Xfit), Scaled(Yptr++,Yfit) );
if (PointType) PX_Symbol (PointType);
for (I=1; I<Imax; I++,Xptr++,Yptr++)
{
if(LineType) PX_Draw (Scaled(Xptr,Xfit), Scaled(Yptr,Yfit) );
else PX_Move (Scaled(Xptr,Xfit), Scaled(Yptr,Yfit) );
if (PointType) PX_Symbol (PointType);
}
PX_Trail (SOLID);
}
int Pct_Fit (Min, Max, Boxes)
/* ======= */
/* Returns a percent fit of the values generated
by the standard scaling algorithm */
double Min,Max; /* data extremes */
int Boxes; /* number of scale divisions */
{
double Delta, Start;
Fit (Min, Max, Boxes, &Start, &Delta);
return ((int) ((Max-Min)*100.0/(Delta*Boxes)+.5));
}
void Scale (Min, Max, Span, Exact, Boxes, Adjust)
/* ===== */
/* Provides scaling values for a set of data */
double Min,Max; /* data extremes */
int Span; /* length of scale, pixels */
int Exact; /* TRUE for ends of scale = Min and Max */
int *Boxes; /* number of scale divisions IN OUT */
SCALING *Adjust; /* the scaling values returned */
{
double floor();
int BestFit,I,MinBox,MaxBox,ThisFit;
if (Exact) {
if (*Boxes) {
Adjust->Start = Min;
Adjust->DeltaB = (Max-Min)/(*Boxes);
}
else { /* choose Boxes until 100% fit found */
BoxTry(Span,&MinBox,&MaxBox);
for (*Boxes=MinBox; *Boxes<=MaxBox; *Boxes+=1)
if ((ThisFit=Pct_Fit(Min,Max,*Boxes))==100) break;
if (*Boxes<=MaxBox)
Fit(Min,Max,*Boxes,&Adjust->Start,&Adjust->DeltaB);
else {
*Boxes = 1;
Adjust->Start = Min;
Adjust->DeltaB = Max-Min;
}
}
}
else { /* NOT Exact */
if (*Boxes<=0) {
BestFit = 0;
*Boxes = 1;
BoxTry(Span,&MinBox,&MaxBox);
for (I=MinBox; I<=MaxBox; I++)
if ((ThisFit=Pct_Fit(Min,Max,I))>BestFit) {
*Boxes = I;
BestFit = ThisFit;
}
}
Fit(Min,Max,*Boxes,&Adjust->Start,&Adjust->DeltaB);
}
Adjust->DeltaP = (double) Span/(Adjust->DeltaB*(*Boxes));
}
int Scaled (Vptr, Vfit)
/* ====== Returns the scaled pixel
location of a data value */
float *Vptr; /* data value */
SCALING *Vfit; /* scaling params */
{
return ( (int) ((*Vptr - Vfit->Start) * Vfit->DeltaP + .5) );
}
void ShowScale (Dir,Boxes,Fit)
/* ========= Displays scaling values */
char Dir;